<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务，帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件，不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types = 1);

namespace app\common\library\sms;

use app\common\library\helper;
use cores\exception\BaseException;
use cores\traits\ErrorTrait;
use Overtrue\EasySms\Exceptions\InvalidArgumentException;
use Overtrue\EasySms\Exceptions\NoGatewayAvailableException;

/**
 * 短信通知模块驱动
 * Class Driver
 * @package app\common\library\sms
 */
class Driver {
	use ErrorTrait;

	// 后台短信配置信息
	private $smsConfig;

	// 当前短信平台 (后台设置)
	private $gateway;
	//global $SMS_TEST_CONFIG;

	/**
	 * 构造方法
	 * Driver constructor.
	 * @param array $smsConfig
	 */
	public function __construct(array $smsConfig) {
		// 配置信息
		$this->smsConfig = $smsConfig;
		// 当前短信平台
		$this->gateway = $this->smsConfig['default'];

	}

	/**
	 * 发送短信通知
	 * @param string $acceptPhone 接收的手机号
	 * @param string $templateCode 短信模板ID
	 * @param array $templateParams 短信模板参数
	 * @return bool
	 * @throws BaseException
	 * @throws InvalidArgumentException
	 */
	public function sendSms(string $acceptPhone, string $templateCode, array $templateParams): bool {
		// 实例化EasySms--注释原来短信-改百度云
		//$easySmsConfig = Config::getEasySmsConfig($this->smsConfig);
		// $easySms = new EasySms($easySmsConfig);
		// try {
		//     // 执行发送短信
		//     $result = $easySms->send($acceptPhone, [
		//         'template' => $templateCode,
		//         'data' => $this->getSmsTemplateData($templateParams),
		//     ]);
		//     // 短信发送成功的错误处理
		//     $sendStatus = $this->resultHandle($result);
		// } catch (NoGatewayAvailableException $e) {
		//     // 短信发送异常的错误处理
		//     $sendStatus = false;
		//     $this->exceptionHandle($e);
		// }

		//$mobile = $this->request->post('mobile');
		$captcha = mt_rand(100000, 999999);

		$data = [
			"signatureId" => 'sms-sign-kazqPM79123', // 签名
			"template" => $templateCode, // 模板
			"mobile" => $acceptPhone, // 手机号
			"contentVar" => $templateParams,
		];

		$ak = 'ALTAK7watsP0T2zjbaiKsbsBW8';
		$sk = '31b097111e7344339132c10144d6e5ef';

		$res = $this->getBaiduApi($data, $ak, $sk);

		log_record([
        	'name'=>'发送短信',
			//'gateway' => $this->smsConfig['default'],
			'res' => $res,
			'acceptPhone' => $acceptPhone,
			'templateCode' => $templateCode,
			'templateParams' => $templateParams,
		
		]);
		//print_r($res);exit;
		
		// 存在异常时抛错
		$sendStatus === false && throwError($this->getError());
		return $sendStatus;
	}

	/**
	 * 短信发送成功的错误处理
	 * @param array $result
	 * @return bool
	 */
	private function resultHandle(array $result): bool {
		// 腾讯云短信错误: 模板ID不正确
		if ($this->gateway === 'qcloud') {
			$response = $result[$this->gateway]['result']['Response']['SendStatusSet'];
			if (isset($response[0]) && isset($response[0]['Code']) && $response[0]['Code'] !== 'Ok') {
				$this->error = '请检查后台短信平台参数和模板ID是否正确';
				return false;
			}
		}
		return true;
	}

	/**
	 * 短信发送异常的错误处理
	 * @param NoGatewayAvailableException $e
	 */
	private function exceptionHandle(NoGatewayAvailableException $e) {
		// 短信发送失败
		$err = $e->getLastException();
		if ($err instanceof \GuzzleHttp\Exception\ClientException) {
			$body = (string) $err->getResponse()->getBody();
			$result = helper::jsonDecode($body);
			if (isset($result['Message'])) {
				// $errMsg = $result['Message'];
				$this->error = '请检查后台短信平台的参数设置';
				return;
			}
			if (isset($result['message'])) {
				$this->error = $result['message'];
				return;
			}
		}
//        if ($err instanceof \Overtrue\EasySms\Exceptions\GatewayErrorException) {
		//            $this->error = $err->getMessage();
		//            return;
		//        }
		$this->error = $err->getMessage();
	}

	/**
	 * 生成短信模板数据
	 * @param array $templateParams
	 * @return array
	 */
	private function getSmsTemplateData(array $templateParams): array {
		if ($this->gateway === 'qcloud') {
			$templateParams = array_values($templateParams);
		}
		return $templateParams;
	}

	//短信

	/**
	 * 接收处理
	 * @param $data     array   短信数据
	 * @param $ak   string      AccessKey
	 * @param $sk   string      SecretKey
	 * @return false|mixed
	 */
	public function getBaiduApi($data, $ak, $sk) {
		$host = 'smsv3.bj.baidubce.com'; // 服务 域名 (北京 smsv3.bj.baidubce.com  ,  苏州  smsv3.su.baidubce.com)
		$uri = '/api/v3/sendSms'; // 接口路径
		$startUtc = gmdate("Y-m-d\TH:i:s\Z"); // utc 时间戳

		$Authorization = $this->getBaiDuAuthorization($startUtc, $uri, $host, $ak, $sk);

		$url = "https://" . $host . $uri;

		$data = json_encode($data, JSON_UNESCAPED_UNICODE);
		$header = [
			'Authorization:' . $Authorization,
			'Host:' . $host,
			'content-type:application/json',
			'x-bce-date:' . $startUtc,
			'Content-Length:' . strlen($data),
		];

		return $this->getBaiDuPostCurl($url, $data, $header);
	}

	/**
	 *  生成签名 认证字符串
	 *  ps: 可使用百度云签名计算工具进行校验
	 * @param  [string]   startUtc   url
	 * @param  [string]   canonicalUri    请求数据
	 * @param  [string]   host    请求头
	 * @param  [string]   ak    AccessKey
	 * @param  [string]   sk    SecretKey
	 */
	function getBaiDuAuthorization($startUtc, $canonicalUri, $host, $ak, $sk) {
		// 签名有效期 (秒)
		$validity = '1800';

		// 代签名头域
		$signedHeaders = 'host;x-bce-date';

		// Host
		$Host = "host:" . $host;

//        $startUtc = '2023-07-28T10:02:36Z';         // utc 时间
		$BceDate = "x-bce-date:" . UrlEncode($startUtc);

		// http 方法
		$httpRequestMethod = "POST";

		$canonicalCan = '';

		// 1: 规范化请求和前缀字符串

		// 规范化请求  由HTTP请求信息规范化后生成
		$canonicalRequest = $httpRequestMethod . "\n" . $canonicalUri . "\n" . $canonicalCan . "\n" . $Host . "\n" . $BceDate;

		// 前缀字符串  由除sk字段外的签名信息生成
		$authStringPrefix = "bce-auth-v1/" . $ak . "/" . $startUtc . "/" . $validity;

		// 2: 派生签名密钥 signingKey  signingKey = HMAC-SHA-256-HEX("sk", authStringPrefix)
		$signingKey = bin2hex(hash_hmac('sha256', $authStringPrefix, $sk, true));

		// 3: 签名摘要 signature  signature = HMAC-SHA-256-HEX(signingKey, canonicalRequest)
		$signature = bin2hex(hash_hmac('sha256', $canonicalRequest, $signingKey, true));

		// 4: 认证字符串 authorization  Authorization = authStringPrefix/signedHeaders/signature
		$Authorization = $authStringPrefix . '/' . $signedHeaders . '/' . $signature;

//        var_dump($startUtc);
		//        var_dump($authStringPrefix);
		//        var_dump($canonicalRequest);
		//        var_dump($signingKey);
		//        var_dump($signature);
		//        var_dump($Authorization);exit;

		return $Authorization;
	}

	/**
	 * post 请求
	 * @param  [string]   url   url
	 * @param  [string]   data    请求数据
	 * @param  [string]   header    请求头
	 */
	function getBaiDuPostCurl($url, $data = null, $header = null) {
		$ch = curl_init();

		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_HEADER, false);
		curl_setopt($ch, CURLOPT_NOBODY, false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

		if (!empty($data)) {
			curl_setopt($ch, CURLOPT_POST, true);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
		}
		if (!empty($header)) {
			curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
		}

		$httpCode = curl_exec($ch);
		$errorCode = curl_errno($ch);
		curl_close($ch);
		if (0 !== $errorCode) {
			return false;
		}

		return json_decode($httpCode, true);
	}

}
